package com.sansecy.customview.view.paystatus;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import androidx.annotation.Nullable;
import androidx.core.util.Pair;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.LinearInterpolator;

import java.util.ArrayList;
import java.util.List;

/**
 * 项目名称：supermarket
 * 类 名 称：PayStatusView
 * 类 描 述：正在支付视图
 * 创建时间：2019-11-07 14:56
 * 创 建 人：sansecy
 */
public class PayingView extends View {

    private List<Dot> mDots = new ArrayList<>();
    private int mDotCount = 9;
    private int mW;
    private int mH;
    private int mRadius;
    private List<String> mColors = new ArrayList<>();
    private int mItemRadius = 10;
    private Paint mPaint = new Paint();
    private ValueAnimator mValueAnimator;

    public PayingView(Context context) {
        super(context);
        init(context, null);
    }

    public PayingView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs);
    }

    private void init(Context context, AttributeSet attrs) {
        mPaint.setColor(Color.BLACK);
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(20);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setTextSize(16);

        mColors.add("#000000");
        mColors.add("#000000");
        mColors.add("#333333");
        mColors.add("#666666");
        mColors.add("#999999");
        mColors.add("#AAAAAA");
        mColors.add("#CCCCCC");
        mColors.add("#EEEEEE");
        mColors.add("#F2F2F2");
        setColorList(mColors);

    }

    public void initAnimation() {
        mValueAnimator = ValueAnimator.ofInt(0, mDotCount);
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                colorIndex = (int) animation.getAnimatedValue();
                Log.d(this.getClass().getName(), "onAnimationUpdate: ");
                invalidate();
            }
        });
        mValueAnimator.setInterpolator(new LinearInterpolator());
        mValueAnimator.setDuration(1000);
        mValueAnimator.setRepeatMode(ValueAnimator.RESTART);
        mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        startAnimation();
    }

    /**
     * 当试图可见性发生改变时触发，不管父视图还是自身
     *
     * @param isVisible 表示是否可见
     */
    @Override
    public void onVisibilityAggregated(boolean isVisible) {
        super.onVisibilityAggregated(isVisible);
        if (isVisible) {
            startAnimation();
        } else {
            stopAnimation();
        }
    }

    @Override
    protected void onDetachedFromWindow() {
        stopAnimation();
        super.onDetachedFromWindow();
    }

    void startAnimation() {
        if (mValueAnimator != null && !mValueAnimator.isRunning()) {
            mValueAnimator.start();
        }
    }

    void stopAnimation() {
        if (mValueAnimator != null && mValueAnimator.isRunning()) {
            mValueAnimator.cancel();
        }
    }

    public void addAnimatorListener(Animator.AnimatorListener animatorListener) {
        if (mValueAnimator == null) {
            initAnimation();
        }
        mValueAnimator.addListener(animatorListener);
    }

    public void setColorList(List<String> colorList) {
        if (colorList == null) {
            throw new IllegalArgumentException("colorList can't be null");
        }
        mDots.clear();
        mColors = colorList;
        for (int i = 0; i < colorList.size(); i++) {
            mDots.add(new Dot());
        }
        mDotCount = mDots.size();
        initAnimation();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mW = w;
        mH = h;
    }

    public static double angle2Radian(double angle) {
        return angle / 180 * Math.PI;
    }

    public void setRadius(int radius) {
        mRadius = radius;
    }

    public void setItemRadius(int itemRadius) {
        mItemRadius = itemRadius;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = measureDimension(200, widthMeasureSpec);
        int height = measureDimension(200, heightMeasureSpec);
        setMeasuredDimension(width, height);

        mRadius = Math.min(width, height) / 2 - mItemRadius * 2;

        float degree = 360f / mDots.size();
        for (int i = 0; i < mDots.size(); i++) {
            Dot dot = mDots.get(i);
            Pair<Double, Double> point = getPoint(mRadius, degree * i);
            dot.set(point.first, point.second);
            String colorString = mColors.get(i);
            dot.setColor(Color.parseColor(colorString));
        }
    }

    /**
     * 给定半径和角度，得到对应的x，y坐标
     *
     * @param radius 半径
     * @param angel  角度
     * @return 坐标对
     */
    private static Pair<Double, Double> getPoint(double radius, float angel) {
        if (angel >= 360) {
            angel = angel - angel / 360 * 360;
        }
        double y = 0;
        double x = 0;
        if (angel >= 0 && angel <= 90) {
            //第二象限
            double radian = angle2Radian(angel);
            y = Math.sin(radian) * radius;
            if (angel == 90) {
                x = 0;
            } else {
                x = Math.cos(radian) * radius;
            }
        } else if (angel > 90 && angel <= 180) {
            //第三象限
            float calculationAngel = 180 - angel;
            double radian = angle2Radian(calculationAngel);
            y = Math.sin(radian) * radius;
            x = -Math.cos(radian) * radius;

        } else if (angel > 180 && angel <= 270) {
            float calculationAngel = angel - 180;
            double radian = angle2Radian(calculationAngel);
            y = -Math.sin(radian) * radius;
            if (calculationAngel == 90) {
                x = 0;
            } else {
                x = -Math.cos(radian) * radius;
            }
        } else if (angel > 270 && angel <= 360) {
            float calculationAngel = 360 - angel;
            double radian = angle2Radian(calculationAngel);
            y = -Math.sin(radian) * radius;
            x = Math.cos(radian) * radius;
        }
        return new Pair<>(x, y);
    }


    public int measureDimension(int defaultSize, int measureSpec) {
        int result;

        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        } else {
            result = defaultSize;   //UNSPECIFIED
            if (specMode == MeasureSpec.AT_MOST) {
                result = Math.min(result, specSize);
            }
        }
        return result;
    }

    int colorIndex = 0;

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.translate(mW / 2, mH / 2);
        for (int i = 0; i < mDots.size(); i++) {
            Dot dot = mDots.get(i);
            if (colorIndex < mDotCount) {
                mPaint.setColor(mDots.get((colorIndex) % mDotCount).color);
            } else {
                colorIndex = colorIndex - mDotCount;
                mPaint.setColor(mDots.get((colorIndex) % mDotCount).color);
            }
            colorIndex++;
            canvas.drawCircle((float) dot.x, (float) dot.y, mItemRadius, mPaint);
        }
    }

    class Dot {
        private double x;
        private double y;
        private int color;

        public int getColor() {
            return color;
        }

        public void setColor(int color) {
            this.color = color;
        }

        public double getX() {
            return x;
        }

        public void setX(double x) {
            this.x = x;
        }

        public void set(double x, double y) {
            this.x = x;
            this.y = y;
        }

        public double getY() {
            return y;
        }

        public void setY(double y) {
            this.y = y;
        }
    }

}